package com.ywu.demand.management.standard.service;

import com.ywu.admin.user.spi.entity.UserEntity;
import com.ywu.admin.user.spi.spi.UserSpi;
import com.ywu.boot.context.YwuContext;
import com.ywu.boot.context.YwuContextHolder;
import com.ywu.boot.exception.YwuRuntimeException;
import com.ywu.common.gson.GsonUtils;
import com.ywu.common.result.CommonResult;
import com.ywu.common.utils.TimerIdGenerateUtil;
import com.ywu.demand.management.standard.data.YwuDemandManageProjectRepository;
import com.ywu.demand.management.standard.data.YwuDemandManageRepository;
import com.ywu.demand.management.standard.dto.YwuDemandManageDto;
import com.ywu.demand.management.standard.dto.YwuDemandManageProjectVersionDto;
import com.ywu.demand.management.standard.entity.YwuDemandManageEntity;
import com.ywu.demand.management.standard.entity.YwuDemandManageProjectEntity;
import com.ywu.demand.management.standard.entity.YwuDemandManageProjectGroupEntity;
import com.ywu.demand.management.standard.entity.YwuDemandManageProjectVersionEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName YwuDemandManageService
 * @Description TODO
 * @Author GroundDemo
 * @Date 2025/3/31 15:32
 * @Version 1.0
 **/
@Service
@Slf4j
public class YwuDemandManageService implements ApplicationContextAware {

    @Autowired
    private YwuDemandManageRepository repository;

    @Autowired
    private YwuDemandManageProjectRepository projectRepository;

    @Autowired
    private UserSpi userSpi;

    private ApplicationContext applicationContext;

    @Autowired
    private YwuDemandManageProjectService service;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
    * @Author GroundDemo
    * @Description 查询需求列表
    * @Date 15:43 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryDemandList(YwuDemandManageDto dto) {
        HashMap<String, Object> res = new HashMap<>();
        // 校验传入的项目ID是否有查询的权限
        CommonResult<Object> result = handleQueryProjectId(dto);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 根据项目ID查询所有符合的需求
        YwuDemandManageEntity search = new YwuDemandManageEntity();
        search.setProjectId(dto.getProjectId());
        search.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        List<YwuDemandManageEntity> entityList = repository.getEntityList(search);
        if (dto.isQueryVersion()) {
            // 查询当前项目的版本信息
            YwuDemandManageProjectVersionDto versionDto = new YwuDemandManageProjectVersionDto();
            versionDto.setProjectId(dto.getProjectId());
            CommonResult<Object> versionInfo = service.queryVersionListForDropDown(versionDto);
            Object data = versionInfo.getData();
            res.put("projectVersionList", data);
        } else {
            res.put("projectVersionList", new ArrayList<>());
        }
        if (CollectionUtils.isEmpty(entityList)) {
            res.put("projectId", dto.getProjectId());
            res.put("demandList", new ArrayList<YwuDemandManageEntity>());
            return CommonResult.success(res);
        }
        // 构建父子关系的层级信息
        List<YwuDemandManageEntity> resList = buildParentSonList(entityList, dto);
        res.put("projectId", dto.getProjectId());
        res.put("demandList", resList);
        return CommonResult.success(res);
    }

    /**
    * @Author GroundDemo
    * @Description 构建父子层级关系
    * @Date 17:15 2025/3/31
    * @Param [entityList, dto]
    * @return java.util.List<com.ywu.demand.management.standard.entity.YwuDemandManageEntity>
    **/
    private List<YwuDemandManageEntity> buildParentSonList(List<YwuDemandManageEntity> entityList, YwuDemandManageDto dto) {
        // 存储所有满足条件的需求集合，包括US和IR （先按照条件过滤，再向上卷积父数据）
        List<YwuDemandManageEntity> matchQueryList = dtoFilter(entityList, dto);
        if (CollectionUtils.isEmpty(matchQueryList)) {
            return new ArrayList<>();
        }
        // 再将过滤后的数据所依赖的父数据添加到集合中
        Set<String> existIds = matchQueryList.stream().map(YwuDemandManageEntity::getId).collect(Collectors.toSet());
        Map<String, YwuDemandManageEntity> sourceEntityMap = entityList.stream().collect(Collectors.toMap(YwuDemandManageEntity::getId, res -> res, (v1, v2) -> v1));
        for (int index = 0; index < matchQueryList.size(); index++) {
            YwuDemandManageEntity entity = matchQueryList.get(index);
            if (!entity.getParentIr().equals("0") && !existIds.contains(entity.getParentIr())) {
                YwuDemandManageEntity tempEntity = sourceEntityMap.get(entity.getParentIr());
                if (Objects.nonNull(tempEntity)) {
                    matchQueryList.add(tempEntity);
                    existIds.add(entity.getParentIr());
                    // 继续从当前位置递归向上卷积
                    upParentEntity(tempEntity, sourceEntityMap, existIds, matchQueryList);
                }
            }
        }
        // 调用用户spi，查询用户账号
        Set<Integer> userIds = matchQueryList.stream().map(YwuDemandManageEntity::getDevUser).collect(Collectors.toSet());
        Set<Integer> testUserId = matchQueryList.stream().map(YwuDemandManageEntity::getTestUser).collect(Collectors.toSet());
        userIds.addAll(testUserId);
        CommonResult<List<UserEntity>> spiRes = userSpi.queryUserByUserIdBatch(new ArrayList<>(userIds));
        if (Objects.isNull(spiRes) || !spiRes.getCode().equals("200")) {
            log.error("query user info error {}", GsonUtils.serialize(spiRes));
            throw new YwuRuntimeException("query user info error");
        }
        List<UserEntity> data = spiRes.getData();
        Map<Integer, UserEntity> userMap = data.stream().collect(Collectors.toMap(UserEntity::getId, res -> res, (v1, v2) -> v1));
        matchQueryList.forEach(res -> {
            if (userMap.containsKey(res.getDevUser())) {
                UserEntity userEntity = userMap.get(res.getDevUser());
                res.setDevUserName(userEntity.getUserAccount());
            }
            if (userMap.containsKey(res.getTestUser())) {
                UserEntity userEntity = userMap.get(res.getTestUser());
                res.setTestUserName(userEntity.getUserAccount());
            }
        });
        // 此时的matchQueryList中是包含了所有符合条件的数据以及他们的上层关系，只需要进行整合设置即可
        // 根据parentIr进行分组
        Map<String, List<YwuDemandManageEntity>> groupByParentIr = matchQueryList.stream().collect(Collectors.groupingBy(YwuDemandManageEntity::getParentIr));
        // 先获取顶层数据
        List<YwuDemandManageEntity> rootList = groupByParentIr.get("0");
        // 遍历根结点，然后设置子结点数据
        for (YwuDemandManageEntity rootEntity : rootList) {
            rootEntity.setParentIr("");
            if (groupByParentIr.containsKey(rootEntity.getId())) {
                List<YwuDemandManageEntity> childrenList = groupByParentIr.get(rootEntity.getId());
                rootEntity.setChildren(childrenList);
                // 子结点再继续往下递归设置子节点的子节点信息
                for (YwuDemandManageEntity child : childrenList) {
                    downChildrenEntity(child, groupByParentIr);
                }
            } else {
                rootEntity.setChildren(new ArrayList<>());
            }
        }
        return rootList;
    }

    /**
    * @Author GroundDemo
    * @Description 向下递归构建父子层级关系
    * @Date 17:53 2025/3/31
    * @Param [currentEntity, groupByParentIr]
    * @return void
    **/
    private void downChildrenEntity(YwuDemandManageEntity currentEntity, Map<String, List<YwuDemandManageEntity>> groupByParentIr) {
        if (groupByParentIr.containsKey(currentEntity.getId())) {
            List<YwuDemandManageEntity> childrenList = groupByParentIr.get(currentEntity.getId());
            currentEntity.setChildren(childrenList);
            // 子结点再继续往下递归设置子节点的子节点信息
            for (YwuDemandManageEntity child : childrenList) {
                downChildrenEntity(child, groupByParentIr);
            }
        } else {
            currentEntity.setChildren(new ArrayList<>());
        }
    }

    /**
    * @Author GroundDemo
    * @Description 向上卷积父需求的数据
    * @Date 17:41 2025/3/31
    * @Param [currentEntity, sourceEntityMap, existIds, matchQueryList]
    * @return void
    **/
    private void upParentEntity(YwuDemandManageEntity currentEntity, Map<String, YwuDemandManageEntity> sourceEntityMap,
                                Set<String> existIds, List<YwuDemandManageEntity> matchQueryList) {
        if (currentEntity.getParentIr().equals("0") || existIds.contains(currentEntity.getParentIr())) {
            return;
        }
        YwuDemandManageEntity tempEntity = sourceEntityMap.get(currentEntity.getParentIr());
        if (Objects.nonNull(tempEntity)) {
            matchQueryList.add(tempEntity);
            existIds.add(currentEntity.getParentIr());
            // 继续从当前位置递归向上卷积
            upParentEntity(tempEntity, sourceEntityMap, existIds, matchQueryList);
        }
    }

    /**
    * @Author GroundDemo
    * @Description 对查询后的所有结果进行过滤
    * @Date 17:18 2025/3/31
    * @Param [entityList, dto]
    * @return java.util.List<com.ywu.demand.management.standard.entity.YwuDemandManageEntity>
    **/
    private List<YwuDemandManageEntity> dtoFilter(List<YwuDemandManageEntity> entityList, YwuDemandManageDto dto) {
        return entityList.stream()
                .filter(res -> !StringUtils.isNotEmpty(dto.getDemandName()) || res.getDemandName().contains(dto.getDemandName()))
                .filter(res -> !StringUtils.isNotEmpty(dto.getDemandType()) || res.getDemandType().equals(dto.getDemandType()))
                .filter(res -> !StringUtils.isNotEmpty(dto.getId()) || res.getId().equals(dto.getId()))
                .filter(res -> !StringUtils.isNotEmpty(dto.getVersionId()) || res.getVersionId().equals(dto.getVersionId()))
                .filter(res -> !StringUtils.isNotEmpty(dto.getDemandStatus()) || res.getDemandStatus().equals(dto.getDemandStatus()))
                .filter(res -> Objects.isNull(dto.getDevUser()) || res.getDevUser().equals(dto.getDevUser()))
                .filter(res -> Objects.isNull(dto.getTestUser()) || res.getTestUser().equals(dto.getTestUser()))
                .collect(Collectors.toList());
    }

    /**
    * @Author GroundDemo
    * @Description 处理请求中的项目ID
    * @Date 16:57 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    private CommonResult<Object> handleQueryProjectId(YwuDemandManageDto dto) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        HashMap<String, Object> res = new HashMap<>();
        // 分为两种情况，一种是带了项目ID的，一种是没有带项目ID的
        if (StringUtils.isEmpty(dto.getProjectId())) {
            // 没有带项目ID，则根据当前用户去查询项目组的用户，取第一个项目ID进行后续的查询
            YwuDemandManageProjectGroupEntity groupEntity = new YwuDemandManageProjectGroupEntity();
            groupEntity.setUserId(String.valueOf(currentContext.getYwuContextUser().getId()));
            YwuDemandManageProjectGroupEntity queryRes = projectRepository.getGroupUserEntity(groupEntity);
            if (Objects.isNull(queryRes)) {
                // 没有项目可查询，返回空即可
                res.put("projectId", "");
                res.put("demandList", new ArrayList<YwuDemandManageEntity>());
                res.put("projectVersionList", new ArrayList<YwuDemandManageProjectVersionEntity>());
                return CommonResult.success(res);
            } else {
                // 将projectId设置为查询到的项目ID
                YwuDemandManageProjectEntity searchEntity = new YwuDemandManageProjectEntity();
                searchEntity.setId(queryRes.getProjectId());
                searchEntity.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
                YwuDemandManageProjectEntity queryResEntity = projectRepository.getEntity(searchEntity);
                if (Objects.isNull(queryResEntity)) {
                    res.put("projectId", "");
                    res.put("demandList", new ArrayList<YwuDemandManageEntity>());
                    res.put("projectVersionList", new ArrayList<YwuDemandManageProjectVersionEntity>());
                    return CommonResult.success(res);
                }
                dto.setProjectId(queryRes.getProjectId());
            }
        } else {
            // 如果携带了项目ID，需要判断当前用户是否可以查看对应项目的数据 - 当前用户是否在项目组中
            YwuDemandManageProjectGroupEntity groupEntity = new YwuDemandManageProjectGroupEntity();
            groupEntity.setUserId(String.valueOf(currentContext.getYwuContextUser().getId()));
            groupEntity.setProjectId(dto.getProjectId());
            YwuDemandManageProjectGroupEntity queryRes = projectRepository.getGroupUserEntity(groupEntity);
            if (Objects.isNull(queryRes)) {
                // 当前用户不在项目组中，返回异常
                log.error("current user can not query since user is not in project group");
                return CommonResult.error().setMessage("current user can not query since user is not in project group");
            }
        }
        return null;
    }

    /**
    * @Author GroundDemo
    * @Description 校验当前用户是否可以添加需求
    * @Date 15:56 2025/3/31
    * @Param [projectId]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    private CommonResult<Object> checkCanCreateOrUpdate(String projectId) {
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        // 根据项目ID查询项目信息
        YwuDemandManageProjectEntity search = new YwuDemandManageProjectEntity();
        search.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        search.setId(projectId);
        YwuDemandManageProjectEntity queryEntity = projectRepository.getEntity(search);
        if (Objects.isNull(queryEntity)) {
            log.error("checkCanCreateOrUpdate project is not exist");
            return CommonResult.error().setMessage("checkCanCreateOrUpdate project is not exist");
        }
        // 判断当前的用户是否为项目的owner
        if (!Objects.equals(currentContext.getYwuContextUser().getId(), queryEntity.getProjectOwner())) {
            // 非owner无法操作用户的添加
            log.error("checkCanCreateOrUpdate project is not owner");
            return CommonResult.error().setMessage("checkCanCreateOrUpdate project is not owner");
        }
        return null;
    }

    /**
    * @Author GroundDemo
    * @Description 校验父需求是否存在
    * @Date 16:20 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    private CommonResult<Object> checkParentIr(YwuDemandManageDto dto) {
        if (StringUtils.isEmpty(dto.getParentIr())) {
            YwuDemandManageEntity search = new YwuDemandManageEntity();
            search.setId(dto.getProjectId());
            YwuDemandManageEntity entity = repository.getEntity(search);
            if (Objects.isNull(entity)) {
                log.error("parent ir id is not exist");
                return CommonResult.error().setMessage("parent ir id is not exist");
            }
        }
        return null;
    }

    /**
    * @Author GroundDemo
    * @Description 校验项目版本是否存在
    * @Date 16:24 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    private CommonResult<Object> checkProjectVersion(YwuDemandManageDto dto) {
        YwuDemandManageProjectVersionEntity versionEntity = new YwuDemandManageProjectVersionEntity();
        versionEntity.setId(dto.getVersionId());
        YwuDemandManageProjectVersionEntity projectVersionEntity = projectRepository.getProjectVersionEntity(versionEntity);
        if (Objects.isNull(projectVersionEntity)) {
            log.error("project version id is not exist");
            return CommonResult.error().setMessage("project version id is not exist");
        }
        return null;
    }

    /**
    * @Author GroundDemo
    * @Description 添加需求
    * @Date 15:54 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> createDemand(YwuDemandManageDto dto) {
        if (StringUtils.isEmpty(dto.getParentIr())) {
            dto.setParentIr("0");
        }
        // 校验当前用户是否可以在当前项目下添加需求
        CommonResult<Object> result = checkCanCreateOrUpdate(dto.getProjectId());
        if (Objects.nonNull(result)) {
            return result;
        }
        // 校验项目版本是否存在
        result = checkProjectVersion(dto);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 校验父需求是否存在
        result = checkParentIr(dto);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 添加数据
        YwuDemandManageEntity insert = new YwuDemandManageEntity();
        BeanUtils.copyProperties(dto, insert);
        insert.setId(TimerIdGenerateUtil.nextId());
        insert.setTenantId(YwuContextHolder.getCurrentContext().getYwuContextTenant().getTenantId());
        insert.createInfo(YwuContextHolder.getCurrentContext().getYwuContextUser().getUserAccount());
        repository.insertDemand(insert);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 校验需求状态的改变
    * @Date 16:32 2025/3/31
    * @Param [dto, queryEntity]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    private CommonResult<Object> checkDemandStatus(YwuDemandManageDto dto, YwuDemandManageEntity queryEntity) {
        if (dto.getDemandStatus().equals(YwuDemandManageEntity.US_TYPE) &&
                queryEntity.getDemandStatus().equals(YwuDemandManageEntity.IR_TYPE)) {
            // 查询当前是否有其他的US或者IR挂载在当前IR下
            YwuDemandManageEntity search = new YwuDemandManageEntity();
            search.setParentIr(queryEntity.getId());
            YwuDemandManageEntity entity = repository.getEntity(search);
            if (Objects.nonNull(entity)) {
                log.error("can not update ir to us, since ir has child us or ir");
                return CommonResult.error().setMessage("can not update ir to us, since ir has child us or ir");
            }
        }
        return null;
    }

    /**
    * @Author GroundDemo
    * @Description 修改需求
    * @Date 16:27 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> updateDemand(YwuDemandManageDto dto) {
        if (StringUtils.isEmpty(dto.getParentIr())) {
            dto.setParentIr("0");
        }
        // 校验需求的原始项目是否有权限修改
        YwuDemandManageEntity search = new YwuDemandManageEntity();
        search.setId(dto.getId());
        YwuDemandManageEntity queryEntity = repository.getEntity(search);
        if (Objects.isNull(queryEntity)) {
            log.error("demand is not exist");
            return CommonResult.error().setMessage("demand is not exist");
        }
        CommonResult<Object> result = checkCanCreateOrUpdate(queryEntity.getProjectId());
        if (Objects.nonNull(result)) {
            return result;
        }
        // 校验当前用户是否可以在当前项目下添加需求
        result = checkCanCreateOrUpdate(dto.getProjectId());
        if (Objects.nonNull(result)) {
            return result;
        }
        // 校验项目版本是否存在
        result = checkProjectVersion(dto);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 校验父需求是否存在
        result = checkParentIr(dto);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 如果当前需求的需求类型发生了修改，则需要校验是否会将当前IR的需求改为US（如果要量IR的需求改为US的话需要确保当前IR下没有挂载其他US或IR）
        result = checkDemandStatus(dto, queryEntity);
        if (Objects.nonNull(result)) {
            return result;
        }
        // 修改数据
        YwuDemandManageEntity update = new YwuDemandManageEntity();
        BeanUtils.copyProperties(dto, update);
        update.updateInfo(YwuContextHolder.getCurrentContext().getYwuContextUser().getUserAccount());
        repository.updateDemand(update);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 删除需求
    * @Date 16:38 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> deleteDemand(YwuDemandManageDto dto) {
        YwuDemandManageEntity search = new YwuDemandManageEntity();
        search.setId(dto.getId());
        YwuDemandManageEntity queryEntity = repository.getEntity(search);
        if (Objects.isNull(queryEntity)) {
            log.error("deleteDemand demand is not exist");
            return CommonResult.error().setMessage("deleteDemand demand is not exist");
        }
        // 校验是否有操作当前项目的权限
        CommonResult<Object> result = checkCanCreateOrUpdate(queryEntity.getProjectId());
        if (Objects.nonNull(result)) {
            return result;
        }
        // 删除数据
        YwuDemandManageEntity delete = new YwuDemandManageEntity();
        delete.setId(dto.getId());
        repository.deleteDemand(delete);
        // 异步删除当前需求下挂载的所有需求
        YwuDemandManageService bean = applicationContext.getBean(YwuDemandManageService.class);
        bean.deleteDemandByParentIr(queryEntity);
        return CommonResult.success(null);
    }

    /**
    * @Author GroundDemo
    * @Description 递归删除需求
    * @Date 16:44 2025/3/31
    * @Param [queryEntity]
    * @return void
    **/
    @Async
    public void deleteDemandByParentIr(YwuDemandManageEntity queryEntity) {
        if (queryEntity.getDemandStatus().equals(YwuDemandManageEntity.US_TYPE)) {
            // US类型不需要递归删除
            return;
        }
        // 根据当前id查询parentIr
        YwuDemandManageEntity search = new YwuDemandManageEntity();
        search.setParentIr(queryEntity.getId());
        List<YwuDemandManageEntity> entityList = repository.getEntityList(search);
        // 根据parentIr删除之后再继续往下递归
        repository.deleteDemandByParentIr(search);
        for (YwuDemandManageEntity entity : entityList) {
            deleteDemandByParentIr(entity);
        }
    }

    /**
    * @Author GroundDemo
    * @Description 查询列表数据局，不生成层级关系
    * @Date 22:40 2025/3/31
    * @Param [dto]
    * @return com.ywu.common.result.CommonResult<java.lang.Object>
    **/
    public CommonResult<Object> queryList(YwuDemandManageDto dto) {
        // 校验当前用户是否有查询项目的权限
        YwuContext currentContext = YwuContextHolder.getCurrentContext();
        YwuDemandManageProjectGroupEntity groupEntity = new YwuDemandManageProjectGroupEntity();
        groupEntity.setProjectId(dto.getProjectId());
        groupEntity.setUserId(String.valueOf(currentContext.getYwuContextUser().getId()));
        YwuDemandManageProjectGroupEntity queryRes = projectRepository.getGroupUserEntity(groupEntity);
        if (Objects.isNull(queryRes)) {
            // 当前用户不在项目组中，返回异常
            log.error("current user can not query since user is not in project group");
            return CommonResult.error().setMessage("current user can not query since user is not in project group");
        }
        // 查询列表
        YwuDemandManageEntity search = new YwuDemandManageEntity();
        BeanUtils.copyProperties(dto, search);
        search.setTenantId(currentContext.getYwuContextTenant().getTenantId());
        List<YwuDemandManageEntity> entityList = repository.getEntityList(search);
        return CommonResult.success(entityList);
    }
}
